package com.mp.approvalreq.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mp.approvalreq.entity.*;
import com.mp.approvalreq.entity.vo.Component;
import com.plusmoney.util.DateTimeHelper;
import com.plusmoney.util.Utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class SummaryUtils {

    private static final Logger logger = LoggerFactory.getLogger(SummaryUtils.class);


    private static final String[] WEEKS = {"周一 ", "周二 ", "周三 ", "周四 ", "周五 ", "周六 ", "周日 "};

    public static Summary getLeaveSummary(Request request, Leave leave) {
        Summary summary = new Summary();
        summary.setContent(leave.getReason());
        String dateTimeDesc = getDateTimeDesc(leave.getRealStartTime());
        if (request.getDefaultType() == Template.COMPENSATORY_LEAVE) {
            dateTimeDesc += "补假";
        } else if (request.getDefaultType() == Template.DAYS_OFF) {
            dateTimeDesc += "调休";
        } else {
            dateTimeDesc += "请假";
        }
        summary.setTime(dateTimeDesc);
        summary.setCost(request.getNaturalContentTimeLast());
        if (StringUtils.isEmpty(summary.getCost())) {
            summary.setCost(leave.getShowTime());
        }
        if (Objects.equals(leave.getIsLeavePause(), 1) && Objects.equals(request.getFinished(), Finished.AGREED)) {
            summary.setState("已销假");
            summary.setColor("#850414");
        } else {
            setState(summary, request);
        }
        return summary;
    }


    public static Summary getOutdoorSummary(Request request, Outdoor outdoor) {
        Summary summary = new Summary();
        summary.setContent(outdoor.getReason());
        String dateTimeDesc = getDateTimeDesc(outdoor.getStart());
        if (request.getDefaultType() == Template.OUTDOOR) {
            dateTimeDesc += "外出";
        } else {
            dateTimeDesc += "出发";
        }
        summary.setTime(dateTimeDesc);
        summary.setCost(getTimeDuration(outdoor.getStart(), outdoor.getEnd()));
        setState(summary, request);
        return summary;
    }

    public static Summary getOvertimeSummary(Request request, List<Overtime> overtimes) {
        Summary summary = new Summary();
        Overtime overtime = overtimes.get(0);
        summary.setContent(overtime.getReason());
        String dateTimeDesc = getDateTimeDesc(request.getCreateTimestamp());
        summary.setTime(dateTimeDesc + "申请");
        summary.setCost(getTimeDescByMinute(OvertimeUtils.getOvertimeDuration(overtimes) / 60));
        setState(summary, request);
        return summary;
    }

    public static Summary getAppendSignSummary(Request request, List<AppendSign> appendSigns) {
        Summary summary = new Summary();
        AppendSign appendSign = appendSigns.get(0);
        summary.setContent(appendSign.getReason());
        String dateTimeDesc = getDateTimeDesc(appendSign.getSignTime());
        summary.setTime(dateTimeDesc + "补卡");
        setState(summary, request);
        return summary;
    }

    public static Summary getExpenseSummary(Request request, List<Expense> expenses) {
        Summary summary = new Summary();
        Expense expense = expenses.get(0);
        String expenseItem = expense.getExpenseItem();
        if (expenses.size() > 1) {
            expenseItem += "等";
        }
        summary.setContent(expenseItem);
        summary.setCost(formatExpenseCost(expense));
        summary.setTime(getDateDesc(DateTimeHelper.parse(expense.getPayDate(), DateTimeHelper.YEAR_MONTH_DAY_PATTERN)) + "支出");
        setState(summary, request);
        return summary;
    }

    private static String formatExpenseCost(Expense expense) {
        BigDecimal totalAmount = expense.getTotalAmount().stripTrailingZeros();
        return totalAmount.toPlainString() + "元";
    }


    public static Summary getOtherSignSummary(Request request) {
        List<TemplateComponent> componentsContent = request.getComponentsContent();
        componentsContent.sort((Comparator.comparingInt(TemplateComponent::getNum)));
        Summary summary = new Summary();

        try {
            setContent(summary, componentsContent);
            setTime(summary, request, componentsContent);
            setCost(summary, componentsContent);
            setState(summary, request);
            if (StringUtils.isNotEmpty(summary.getContent()) && summary.getContent().length() > 20) {
                summary.setContent(summary.getContent().substring(0, 20) + "...");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            EmailUtils.sendErrorMail("处理列表信息出错",JSONObject.toJSONString(e));
        }
        return summary;
    }

    private static void setCost(Summary summary, List<TemplateComponent> componentsContent) {
        for (TemplateComponent component : componentsContent) {
            if (Objects.equals(component.getShowType(), TemplateComponent.SHOW_TYPE_COST)) {
                String value = component.getValue();
                if (StringUtils.isEmpty(value) || value.contains("[")) {
                    break;
                }
                if (component.getType() == ContentType.MONEY || component.getType() == ContentType.TOTAL_MONEY) {
                    summary.setCost(value + "元");
                    return;
                }
                if (component.getType() == ContentType.TIME_RANGE) {
                    TemplateComponent nextComponent = ComponentUtils.getComponentByNumber(componentsContent, component.getNum() + 1);
                    if (Utils.isNull(nextComponent)) {
                        break;
                    }
                    if (!ValidateUtil.isValidDateTime(component.getValue()) || !ValidateUtil.isValidDateTime(nextComponent.getValue())) {
                        break;
                    }
                    Date start = DateTimeHelper.parse(component.getValue(), DateTimeHelper.YEAR_MONTH_DAY_HOUR_MINUTE_PATTERN);
                    Date end = DateTimeHelper.parse(nextComponent.getValue(), DateTimeHelper.YEAR_MONTH_DAY_HOUR_MINUTE_PATTERN);
                    summary.setCost(getTimeDuration(start, end));
                    return;
                }
            }
        }
        for (TemplateComponent component : componentsContent) {
            String value = component.getValue();
            if (StringUtils.isEmpty(value) || value.contains("[")) {
                continue;
            }
            if (component.getType() == ContentType.MONEY || component.getType() == ContentType.TOTAL_MONEY) {
                summary.setCost(value + "元");
                return;
            }
            if (component.getType() == ContentType.TIME_RANGE) {
                TemplateComponent nextComponent = ComponentUtils.getComponentByNumber(componentsContent, component.getNum() + 1);
                if (Utils.isNull(nextComponent)) {
                    continue;
                }
                if (!ValidateUtil.isValidDateTime(component.getValue()) || !ValidateUtil.isValidDateTime(nextComponent.getValue())) {
                    continue;
                }
                Date start = DateTimeHelper.parse(component.getValue(), DateTimeHelper.YEAR_MONTH_DAY_HOUR_MINUTE_PATTERN);
                Date end = DateTimeHelper.parse(nextComponent.getValue(), DateTimeHelper.YEAR_MONTH_DAY_HOUR_MINUTE_PATTERN);
                summary.setCost(getTimeDuration(start, end));
                return;
            }
        }
    }

    private static void setTime(Summary summary, Request request, List<TemplateComponent> componentsContent) {
        for (TemplateComponent component : componentsContent) {
            if (Objects.equals(component.getShowType(), TemplateComponent.SHOW_TYPE_TIME)) {
                if (ValidateUtil.isValidDate(component.getValue())) {
                    summary.setTime(getDateDesc(DateTimeHelper.parse(component.getValue(), DateTimeHelper.YEAR_MONTH_DAY_PATTERN)));
                    return;
                }
                if (ValidateUtil.isValidDateTime(component.getValue())) {
                    summary.setTime(getDateTimeDesc(DateTimeHelper.parse(component.getValue(), DateTimeHelper.YEAR_MONTH_DAY_HOUR_MINUTE_PATTERN)));
                    return;
                }
            }
        }
        summary.setTime(getDateTimeDesc(request.getCreateTimestamp()) + "申请");
    }


    private static void setContent(Summary summary, List<TemplateComponent> componentsContent) {
        for (TemplateComponent component : componentsContent) {
            if (Objects.equals(component.getShowType(), TemplateComponent.SHOW_TYPE_DESCRIBE)) {
                if (component.getType() == ContentType.COMPONENT_GROUP) {
                    summary.setContent(getGroupContent(component));
                } else {
                    summary.setContent(component.getValue());
                }
                return;
            }
        }
        for (TemplateComponent component : componentsContent) {
            String value = component.getValue();
            if (StringUtils.isBlank(value) && Utils.isEmpty(component.getGroupContents())) {
                continue;
            }
            switch (component.getType()) {
                case ContentType.SINGLE_LINE:
                case ContentType.TEXT:
                case ContentType.NUMBER:
                case ContentType.SINGLE_CHOSEN:
                    summary.setContent(value);
                    return;
                case ContentType.LOCATION:
                    if (value.contains("[")) {
                        List<String> values = JSONObject.parseArray(value, String.class);
                        if (Utils.isEmpty(values)) {
                            continue;
                        }
                        summary.setContent(values.get(0));
                        return;
                    }
                    break;
                case ContentType.MULTI_CHOSEN:
                    List<String> values = JSONObject.parseArray(value, String.class);
                    if (Utils.isEmpty(values)) {
                        continue;
                    }
                    summary.setContent(values.get(0));
                    return;
                case ContentType.COMPONENT_GROUP:
                    String content = getGroupContent(component);
                    logger.info("取组件集内容:{}", content);
                    if (StringUtils.isNotEmpty(content)) {
                        summary.setContent(content);
                        return;
                    }
            }
        }
    }

    private static String getGroupContent(TemplateComponent component) {
        List<GroupContent> groupContents = component.getGroupContents();
        if (Utils.isEmpty(groupContents)) {
            return null;
        }
        String result = null;
        GroupContent firstContent = Utils.getFirst(groupContents);
        if (Utils.isNotNull(firstContent)) {
            List<Component> values = firstContent.getValue();
            List<Component> components = values.stream().filter(v -> Objects.equals(v.getNum(), component.getGroupShowNum())).collect(Collectors.toList());
            if (Utils.isEmpty(components)) {
                components = values.stream().filter(v -> Objects.equals(v.getType(), ContentType.SINGLE_LINE) || Objects.equals(v.getType(), ContentType.TEXT)).collect(Collectors.toList());
            }
            for (Component com : components) {
                if (StringUtils.isEmpty(com.getValue())) {
                    continue;
                }
                if (com.getType() == ContentType.GROUP_LOCATION) {
                    JSONObject jsonObject = JSON.parseObject(com.getValue());
                    String location = jsonObject.getString("location");
                    result = location == null ? "" : location;
                } else {
                    result = com.getValue();
                }
            }
        }
        if (StringUtils.isNotEmpty(result) && groupContents.size() > 1) {
            result += "等";
        }
        return result;
    }

    private static void setState(Summary summary, Request request) {
        switch (request.getFinished()) {
            case Finished.APPROVING:
                summary.setState("待批准");
                summary.setColor("#ffa91f");
                break;
            case Finished.AGREED:
                if (Objects.equals(request.getFinancialStatus(), 1)) {
                    summary.setState("待付款");
                    summary.setColor("#ffa91f");
                } else if (Objects.equals(request.getFinancialStatus(), 2)) {
                    summary.setState("已付款");
                    summary.setColor("#38c972");
                } else {
                    summary.setState("已批准");
                    summary.setColor("#38c972");
                }
                break;
            case Finished.ARCHIVED:
                summary.setState("已归档");
                summary.setColor("#aaaaaa");
                break;
            case Finished.REFUSED:
                summary.setState("已驳回");
                summary.setColor("#f75c4c");
                break;
            case Finished.CALLING_BACK:
                summary.setState("已撤销");
                summary.setColor("#aaaaaa");
                break;
            case Finished.CANCELLED:
                summary.setState("已作废");
                summary.setColor("#aaaaaa");
                break;
            default:
                break;
        }
    }


    public static String getDateTimeDesc(Date date) {
        StringBuilder sb = new StringBuilder(DateTimeHelper.format(date, "yy/MM/dd "));
        int week = Integer.parseInt(DateTimeHelper.format(date, "u")) - 1;
        sb.append(WEEKS[week]);
        sb.append(DateTimeHelper.format(date, "HH:mm "));
        return sb.toString();
    }

    private static String getDateDesc(Date date) {
        StringBuilder sb = new StringBuilder(DateTimeHelper.format(date, "yy/MM/dd "));
        int week = Integer.parseInt(DateTimeHelper.format(date, "u")) - 1;
        sb.append(WEEKS[week]);
        return sb.toString();
    }

    private static String getTimeDuration(Date start, Date end) {
        int minute = (int) ((end.getTime() - start.getTime()) / DateUtils.MILLIS_PER_MINUTE);
        return getTimeDescByMinute(minute);
    }

    private static String getTimeDescByMinute(int minute) {
        int day = 0;
        int hour = 0;

        if (minute >= 60) {
            hour = minute / 60;
            minute %= 60;
        }

        if (hour >= 24) {
            day = hour / 24;
            hour %= 24;
        }
        StringBuilder sb = new StringBuilder();
        if (day > 0) {
            sb.append(day).append("天");
        }
        if (hour > 0) {
            sb.append(hour).append("小时");
        }
        if (minute > 0) {
            sb.append(minute).append("分钟");
        }
        return sb.toString();
    }

}


